package cn.anl.controller;

import cn.anl.constant.RedisConstant;
import cn.anl.pojo.SysUser;
import cn.anl.result.ApiResponse;
import cn.anl.result.ApiResponseEnum;
import cn.anl.service.RedisService;
import cn.anl.service.UserDetailsWrap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author 安奈
 * @CreateTime 2024-07-04  09:12
 * @Desc TODO
 */
@RestController
@RequestMapping("oauth")
@Slf4j
public class AuthController {
    @Resource
    private TokenEndpoint tokenEndpoint;
    @Resource
    private RedisService redisService;
    @Resource
    private RedisTokenStore redisTokenStore;

    /**
     * @Desc 获取token实现登录
     * @Author 安奈
     * @Date 2024/7/5 11:06
     * @Param: principal
     * @Param: parameters
     **/
    @RequestMapping("/token")
    public ApiResponse<Object> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
        return ApiResponse.success(tokenEndpoint.postAccessToken(principal, parameters).getBody());
    }

    @PostMapping("/info")
    public ApiResponse<Object> getUserInfo(@RequestBody String token) {
        OAuth2AccessToken oAuth2AccessToken = redisTokenStore.readAccessToken(token);
        //如果redis读到的token为空，说明失效或被清除了
        if (oAuth2AccessToken != null) {
            OAuth2Authentication oAuth2Authentication = redisTokenStore.readAuthentication(token);
            UserDetailsWrap userDetailsWrap = (UserDetailsWrap) oAuth2Authentication.getPrincipal();
            userDetailsWrap.getUser().setPassword("");
            Collection<? extends GrantedAuthority> authorities = userDetailsWrap.getAuthorities();
            ArrayList<String> permissionCodes = new ArrayList<>();
            if (!authorities.isEmpty()) {
                for (GrantedAuthority authority : authorities) {
                    String permissionCode = authority.getAuthority();
                    permissionCodes.add(permissionCode);
                }
            }
            userDetailsWrap.getUser().setAuthorities(permissionCodes);
            //@TODO 目前只考虑单用户登录情况，并发下RedisConstant.USER_INFO.getKey()需要带上用户的token
            redisService.setCacheObject(RedisConstant.USER_INFO.getKey(), userDetailsWrap.getUser());
            return ApiResponse.success(userDetailsWrap.getUser());
        }
        return ApiResponse.error(ApiResponseEnum.INVALID_AUTHORIZATION_CERTIFICATE.getCode()
                , ApiResponseEnum.INVALID_AUTHORIZATION_CERTIFICATE.getMessage());
    }

    /**
     * @Desc 退出方法
     * @Author 安奈
     * @Date 2024/7/6 9:32
     * @Param: token
     **/
    @PostMapping("/logout")
    public ApiResponse<Object> postLogout(@RequestBody String token) {
        OAuth2AccessToken oAuth2AccessToken = redisTokenStore.readAccessToken(token);
        //如果redis读到的token为空，说明失效或被清除了
        if (oAuth2AccessToken != null) {
            redisTokenStore.removeAccessToken(oAuth2AccessToken);
            OAuth2RefreshToken refreshToken = oAuth2AccessToken.getRefreshToken();
            //清除缓存的用户信息
            redisService.deleteObject(RedisConstant.USER_INFO.getKey());
            redisTokenStore.removeRefreshToken(refreshToken);
        }
        return ApiResponse.success("退出成功");
    }
}
